namespace ghost
{
	/**场景管理器，编写场景业务，如创建场景元素，场景角色排序、查询等*/
	export class SceneManager extends map2D.SceneManagerBase
	{	
		public static instance:SceneManager;		
		public module:ghost.Module;		
		public autoRun:boolean;				
		// public initX:number;
		public monsterScl:number;
		public driftScl:number;
		public playerScl:number;
		/**是否暂停角色*/
		public _pausedRole:boolean;
		/**是否暂停角色及其物体*/
		public _pausedRoleObj:boolean;
		protected _battlePaused:boolean;
		// private _screenMonsters:any[];
		// private _screenObjects:any[];
		public warnFlag:boolean;
		
		
		public constructor(gameContainer:GYSprite,sceneLayer:GYSprite,sceneBaseWidth:number,sceneBaseHeight:number,m:ghost.Module)
		{			
			super(gameContainer, sceneLayer,sceneBaseWidth,sceneBaseHeight);			
			let s= this;
			SceneManager.instance = s;
			s.module = m;			
			s.warnFlag = true;
			s._paused = false;
			s._pauseTime = 0;	
			s._pauseStartTime = 0;			
			PoolUtil.registerClassInfo(MyPlayer, "ghost.MyPlayer", ["ghost.Player","ghost.GameRole","ghost.AniRole","ghost.Role"]);			
			
			s.roleQueueMgr.addQueue(RoleType.PLAYER,Player,true,"ghost.Monster", ["ghost.GameRole","ghost.AniRole","ghost.Role"]);
			s.roleQueueMgr.addQueue(RoleType.MONSTER,Monster,true,"ghost.Player", ["ghost.GameRole","ghost.AniRole","ghost.Role"]);
			s.roleQueueMgr.addQueue(RoleType.MONSTER2,Monster,true,"ghost.Monster", ["ghost.GameRole","ghost.AniRole","ghost.Role"]);
			s.roleQueueMgr.addQueue(RoleType.DRIFT_OBJ,DriftObj,true,"ghost.DriftObj", ["ghost.ObjBase","ghost.GameRole","ghost.AniRole","ghost.Role"]);			
			s.roleQueueMgr.addQueue(RoleType.EFFECT,EffectObj,false,"ghost.EffectObj",["ghost.ObjBase","ghost.GameRole","ghost.AniRole","ghost.Role"]);			
			s.roleQueueMgr.addQueue(RoleType.BAR_OBJ,BarObj,false,"ghost.BarObj",["ghost.NoDepthObj","ghost.ObjBase","ghost.GameRole","ghost.AniRole","ghost.Role"]);
			s.roleQueueMgr.addQueue(RoleType.NUMBER_OBJ,NumberObj,false,"ghost.NumberObj",["ghost.NoDepthObj","ghost.ObjBase","ghost.GameRole","ghost.AniRole","ghost.Role"]);			
		}
		public createRoleByCfg(owner:map2D.IRole,cfg:any,roleType:number=0,createSts:number=0,createDir:number=0,x:number=0,y:number=0,sceneParam:any=null):map2D.IRole
		{
			var r:Role;			
			let s= this;						
			r = <Role>s.roleQueueMgr.create(cfg,roleType,owner);
			// if(sceneParam)
			// 	r.setSceneParam(sceneParam);
			r.create(createSts, createDir, x, y);
			if(s._paused)
				r.pause();
			return r;
		}
		public setMyPlayer(player:map2D.IMyPlayer):void
		{
			let s= this;
			s._myPlayer = player;
			s.module.dirBoard.setData(player);
			s.module.skillBoard.setData(<any>player,[]);			
		}
		public removeFromSceneVec(r:map2D.IRole):void
		{			
			let type:number;			
			let s= this;
			type = r.roleListType;
			s.roleQueueMgr.removeFromSceneVec(r);
			super.removeFromSceneVec(r);			
		}
		public addToSceneVec(r:map2D.IRole):void
		{
			super.addToSceneVec(<map2D.IRole>r)
			let s = this;
			s.roleQueueMgr.addToSceneVec(r);
		}		
		
		public clearScene():void
		{
			let s= this;			
			Main.result = 0;
			if(s.module.loseUI && s.module.loseUI.parent)
				s.module.loseUI.hide();
			if(s.module.winUI && s.module.winUI.parent)
				s.module.winUI.hide();
			s.roleQueueMgr.foreachQueue((queue:map2D.RoleQueue<any>) => {
				queue.clearList();
			},s);	
			super.clearScene();
				
		}
		protected resetDp():void
		{
			let s =this;			
            s.roleQueueMgr.foreachQueue((queue:map2D.RoleQueue<any>) => {
				if(queue.isDepth)
					s.addToDepthList(queue.list);	
			},s);	
			super.resetDp();
		}				
		public loop(t:number):void
		{
			let s= this;			
			super.loop(t);			
			t = s.timeTick;
			if(s.sceneLogic.inited)
				s.sceneLogic.loop(t);			
			let arr:Effect[];
			let len:number;
			for(var key in Effect.effectList)
			{
				arr = Effect.effectList[key];
				len = arr.length;
				while(--len > -1)
					arr[len].excLoop(t);
			}
			s.mapPosChanged = false;
		}
		protected enterLoop(t:number):void
		{
			let s = this;				
			s.roleQueueMgr.foreachQueue((queue:map2D.RoleQueue<any>) => {
				s.update(t,queue.list);	
			});			
			super.enterLoop(t);
		}
		protected exitLoop(t:number):void
		{
			let s = this;									            
			super.exitLoop(t);			
			s.roleQueueMgr.foreachQueue((queue:map2D.RoleQueue<any>) => {
				s.updateLater(t,queue.list);	
			}, s);			
		}
		public createMonster(monsterID:string,absX:number,absY:number):void
		{
			let s= this;			
			s.createRoleByCfg(RoleConfig.getRoleConfig(monsterID), {absX:absX, abxY: absY});
		}
		public createObjectByCfg(owner:Role,roleType:number,cfg:any,createSts:number=0,createDir:number=0,x:number=0,y:number=0):map2D.IRole
		{
			var r:map2D.IRole;			
			let s= this;			
			r = s.roleQueueMgr.create(cfg,roleType,owner);			
			r.create(createSts,createDir,x,y);
			return r;
		}
		public createObj(objID:string, absX:number,absY:number,owner:AniRole, type:number = RoleType.DRIFT_OBJ,param:any=null):void
		{
			let s= this;
			if(type == RoleType.DRIFT_OBJ)
			{				
				let obj:DriftObj = <DriftObj>s.createRoleByCfg(RoleConfig.getObjConfig(objID), {absX:absX, absY: absY, speed:32});
				obj.setOwner(owner);
				obj.setSceneParam(param);
			}
			else if(type == RoleType.EFFECT)			
			{				
				let obj:EffectObj = <EffectObj>s.createRoleByCfg(RoleConfig.getObjConfig(objID), {absX:absX, absY: absY});
				obj.setOwner(owner);
			}
		}
		public createDriftObj(owner:GameRole,roleType:number,objID:string,x:number,y:number,sts:number=0,dir:number=0):DriftObj
		{			
			let driftObj:DriftObj = <DriftObj>this.createObjectByCfg(owner, roleType, RoleConfig.getObjConfig(objID),sts,dir,x,y);
			driftObj.setSceneParam({camp:owner._camp});				
			return driftObj;
		}
		public createEffect(owner:Role,roleType:number,objID:string,x:number,y:number,sts:number=0,dir:number=0,layerType:number=NaN):EffectObj
		{	
			return <EffectObj>this.createObjectByCfg(owner, roleType, RoleConfig.getEffectObj(null, objID, layerType), sts,dir,x,y);						
		}
		public createNoDepthObj(owner:Role,roleType:number,objID:string,x:number,y:number,sts:number=0,dir:number=0,layerType:number=NaN):NoDepthObj
		{			
			return <NoDepthObj>this.createObjectByCfg(owner, roleType, RoleConfig.getEffectObj(null,objID, layerType), sts,dir,x,y);
		}
		public createBarObj(owner:AniRole,roleType:number,objID:string,x:number,y:number,sts:number=0,dir:number=0):BarObj
		{
			return <BarObj>this.createObjectByCfg(owner, roleType, RoleConfig.getObjConfig(objID),sts,dir,x,y);
		}
		public createNumberObj(owner:GameRole,roleType:number,objID:string,x:number,y:number,num:string="-9999",numSkin:ILabelData=null):NumberObj
		{
			let numberObj:NumberObj = <NumberObj>this.createObjectByCfg(owner, roleType, RoleConfig.getObjConfig(objID),StsType.STAND,map2D.DirectionType.RIGHT,x,y);						
			if(numSkin)
				numberObj.setNumSkin(numSkin);
			numberObj.setName(num);						
			return numberObj;
		}
		public roleHit(rA:MyPlayer,rB:GameRole):void
		{
			let s =this;
			// if(rB.cfg.express == null)
			// {
			// 	s.addDelRole(rB);
			// 	s.expressChange();
			// 	return;
			// }
			// if(rA.sts != StsType.JUMP && rA.expressLab.result < rB.expressLab.result || rA.sts != StsType.ATTACK && rA.expressLab.result > rB.expressLab.result)
			// {
			// 	rA.setOperSts(StsType.DEATH,rA.direction);				
			// 	console.log("失败!!!!");
			// }
			// else
			// {
			// 	rB.setOperSts(StsType.DEATH,rA.direction);
			// 	MyPlayerData.getInstance().addScore(1);
			// 	s.module.scoreLab.text = "当前得分" + MyPlayerData.getInstance().score + "\n行走" + s._mapX + "米";
			// }
		}
		public setMapXY(toX:number,toY:number,reset:boolean):void		
		{
			super.setMapXY(toX,toY,reset);			
		}
		/**暂停战斗（包括角色和特效）**/
		public pauseBattle(val:boolean):void
		{
			let s = this;			
			if(s._battlePaused == val)return;
			s._battlePaused = val;
			if(s._battlePaused)
			{
				s.pauseSceneRole(true, true);
				Effect.pauseAll();
			}
			else
			{
				s.pauseSceneRole(false, true);
				Effect.resumeAll();
			}
		}
		/**暂停角色(仅仅角色，不包括特效和场景计时器)**/
		public pauseSceneRole(val:boolean=false, includeObj:boolean=false):void
		{
			let s = this;
			let roles:GameRole[];
			let len:number;
			let r:GameRole;
			if(s._pausedRole == val && s._pausedRoleObj == includeObj)return;
			s._pausedRole = val;
			s._pausedRoleObj = includeObj;	
			roles = s.getAllMonsterList();
			len = roles.length;
			while(--len>-1)
			{
				r = roles[len];
				if(r._layerType == map2D.LayerType.DEF)
					continue;
				val?r.pause(includeObj):r.resume(includeObj);
			}				
			roles = s.getPlayerList();
			len = roles.length;
			while(--len>-1)
			{
				r = roles[len];
				if(r._layerType == map2D.LayerType.DEF)
					continue;
				val?r.pause(includeObj):r.resume(includeObj);
			}				
			let my:MyPlayer = <MyPlayer>s.myPlayer;
			if(my)
				val?my.pause(includeObj):my.resume(includeObj);

			if(includeObj)
			{
				roles = s.getDriftObjList();
				len = roles.length;
				while(--len>-1)
				{
					r = roles[len];
					val?r.pause():r.resume();
				}
			}			
		}
		public getMonsterList():Monster[]
		{
			return this.roleQueueMgr.getList(RoleType.MONSTER);
		}
		public getMonsterList2():Monster[]
		{
			return this.roleQueueMgr.getList(RoleType.MONSTER2);
		}
		public getAllMonsterList():Monster[] {
			let s = this;
			let arr = s.getMonsterList();
			arr = arr.concat(s.getMonsterList2());
			return arr;
		}
		public getMonsterListByCamp(camp: number):Monster[]
		{
			let s = this;
			if(camp == -1)
				return s.getAllMonsterList();
			return camp == 1?s.getMonsterList():s.getMonsterList2();
		}
		public getPlayerList():Player[]
		{
			return this.roleQueueMgr.getList(RoleType.PLAYER);
		}
		public getDriftObjList():DriftObj[]
		{
			return this.roleQueueMgr.getList(RoleType.DRIFT_OBJ);
		}		
		
		public findPlayerByUserName(userName:string):Role
		{
			let s= this;
			let len:number;
			let list:Role[]=s.getPlayerList();
			var role:Role;
			len = list.length;
			for (var i:number=1;i<len;++i)
			{
				role=list[i];
				if (role.userName == userName && !role.isDel())
					return role;
			}
			return null;
		}
		public findMonsterByRoleID(camp:number,roleID:string):Monster[]
		{
			let arr:Monster[];
			if(camp == CampType.CAMP_1)
			{
				arr = this.getMonsterList();
			}
			else if(camp == CampType.CAMP_2)
			{
				arr = this.getMonsterList2();
			}
			let len:number;
			let result:Monster[] = [];
			len = arr.length;
			while(--len>-1)
			{
				if(arr[len].roleID == roleID)
					result.push(arr[len]);
			}
			return result;
		}
		/**查询主角附近某个类型的怪物
		 * @param type 1 床 2 门
		*/
		public findNearMonsterByType(type:number=1):Monster
		{
			let s = this;
			let arr:Monster[];
			arr = this.getMonsterList();
			let len:number,dis:number,minDis:number;
			let result:Monster;
			let myPlayer:MyPlayer;
			let m:Monster;			
			minDis = Number.MAX_VALUE;
			myPlayer = <MyPlayer>s.myPlayer;
			len = arr.length;
			while(--len>-1)
			{
				m = arr[len];				
				if(type == 1 && m.isBed() || type == 2 && m.isDoor())
				{
					dis = PositionUtil.calculateDistance(myPlayer.absX,myPlayer.absY,m.absX, m.absY);
					if(dis < minDis)
					{
						result = m;
						minDis = dis;
					}
				}				
			}
			return result;
		}
		/**根据类型和房间索引查询怪物
		 * @param type 1 床 2 门
		 * @param roomIndex 房间索引
		*/
		public findMonsterByRoomInd(type:number=1, roomIndex:number):Monster[]
		{			
			let len:number;
			let arr:Monster[],result:Monster[]=[];
			let m:Monster;
			arr = this.getMonsterList();
			len = arr.length;
			while(--len>-1)
			{
				m = arr[len];				
				if(type == 1 && m.isBed() || type == 2 && m.isDoor())
				{
					if(m.roomIndex == roomIndex)
					{
						result.push(m);
					}					
				}				
			}
			return result;
		}
		
        public kDown(keyCode: number): void
		{
			let s =this;
			let k:GYKeyboard;
			if(!s._sceneTouchabled)return;
			let myPlayer:MyPlayer = <MyPlayer>s._myPlayer;
			k = GYKeyboard.getInstance();			
			let pos:number = PublicVar.skillKey.indexOf(keyCode);
			if (pos == 13) // space
			{
				s.module.skillBoard.excSkill(StsType.JUMP);					
				return;
			}	
			if(pos == 12)
			{		
				// myPlayer.addFlowNumber(RoleID.HP_NUM, "123456789", 0, -s.myPlayer._headJumpH);
				// myPlayer.setAtkTarget([s.getMonsterList2()[0]]);
				// myPlayer.operSkill(myPlayer._skillList[0]);
				myPlayer.setOperSts(StsType.FALL);
				// s.module.skillBoard.excSkill(StsType.ATTACK);				
				return;
			}
			
			if (pos == 0) // 1~8
			{				
				var oper:number=Number(s._myPlayer.roleID + "0" + (pos+1));				
				s.module.skillBoard.excSkill(oper);					
				return;
			}						
			if (pos < 0)
				return;			
			if(k.isKeyDown(Laya.Keyboard.W) || k.isKeyDown(Laya.Keyboard.S) || k.isKeyDown(Laya.Keyboard.A) || k.isKeyDown(Laya.Keyboard.D))
			{
				s.keyDirect();
				return;
			}
		}
        public kUp(keyCode: number): void
		{
			var k:GYKeyboard = GYKeyboard.getInstance();
			let s= this;
			if(!s._sceneTouchabled)return;
			var pos:number;
			var oper:number=-1;				
			let myPlayer:MyPlayer = <MyPlayer>s._myPlayer;
			pos=PublicVar.skillKey.indexOf(keyCode);
			if(pos == 8 || pos == 9 || pos == 10 || pos == 11)
			{
				s.keyDirect();				
			}
			if(pos == 13)
				oper = StsType.JUMP;
			else 
			{				
				if(pos == 12)
					oper = StsType.ATTACK;			
				else if(pos >=0 && pos < 8 || pos == 13)							
					oper = Number(myPlayer.roleID + "0" + (pos+1));							
				if(oper >= 0 && myPlayer.isCDOk(myPlayer._skillList[0]))					
					s.module.skillBoard.excSkillEnd(oper);
			}			
		}
		protected keyDirect():number
		{
			let direct:number;
			let s = this;
			direct = super.keyDirect();
			if(direct == -1)
			{				
				s.module.dirBoard.touchEnd();				
				return direct;
			}
			s.module.dirBoard.touchBegin();			
			s.module.dirBoard.touchDir(map2D.DirectionType.getDirectorAngle(direct),500);			
			return direct;
		}
		
		protected configSet(sceneCfg:any):void
		{
			let s = this;			
			s._sceneCfg = sceneCfg;
			super.configSet(sceneCfg);
			let info:any = sceneCfg.sceneInfo;
			// s._screenMonsters = sceneCfg.screenMonster.concat();
			// s._screenObjects = sceneCfg.screenObjects.concat();
			s.driftScl = info.driftScl?info.driftScl:1;
			s.monsterScl = info.monsterScl?info.monsterScl:1;
			s.playerScl = info.playerScl?info.playerScl:0.4;
		}
		public resetSceneConfig(sceneCfg:any):boolean
		{
			let s = this;			
			let m:MyPlayer;
			let initX:number,initY:number;
			
			if(s._sceneCfg && s._sceneCfg == sceneCfg)
			{
				s._initMapX = sceneCfg.sceneInfo.mapInitX;
				s._initMapY = sceneCfg.sceneInfo.mapInitY;								
			}
			else
				s.configSet(sceneCfg);		
			s.sceneLogic.configSet(sceneCfg);
			initX = s._initMapX;
			initY = s._initMapY;
			let absX:number,absY:number;
			absX = initX + (s.sceneWidth >> 1);
			absY = initY + (s.sceneHeight >> 1)
			if(s._myPlayer == null)
			{
				m = s.createMyPlayer(absX,absY);
			}
			else
			{
				m = <MyPlayer>s._myPlayer;
				m.absX = absX;
				m.absY = absY;
			}
			
			s.setMapXY(s._initMapX,s._initMapY, true);	
			return true;		
		}
		/**创建主角到指定位置*/
		public createMyPlayer(absX:number,absY:number):MyPlayer
		{
			let s= this;
			let m:MyPlayer;
			let sceneCfg:any = s._sceneCfg;			
			s.setMyPlayer(<any>PoolUtil.fromPool(MyPlayer));
			m = (<MyPlayer>s._myPlayer);						
			let roleCfg:any;
			if(sceneCfg.myPlayer)
				MyPlayerData.getInstance().roleCfg = sceneCfg.myPlayer;			
			roleCfg = MyPlayerData.getInstance().roleCfg;
			m.parseConfig(RoleType.PLAYER, roleCfg);			
			// s.initX = sceneCfg.playerInitX?sceneCfg.playerInitX:s.getDefault().role_init_x;
			// m.setInitialSts(2, s.initX, sceneCfg.playerInitY?sceneCfg.playerInitY:s.getDefault().role_init_y,1);			
			
			m.create(StsType.STAND, map2D.DirectionType.RIGHT, absX, absY);				
			if(sceneCfg.playerMoveSpeed)
				m.speed = sceneCfg.playerMoveSpeed;	
			GameRole.roleDataSet(m, roleCfg);
			return m;
		}
		/**初始化创建场景*/
		protected createScene(sceneCfg:any):void
		{
			let s = this;
			super.createScene(sceneCfg);
			s.sceneLogic.init();
			s.autoRun = false;
			GameManager.getInstance().isGameOver = false;
			s.warnFlag = false;

			let obj:any;
			let len:number;
			let r:Monster;
			if(s._sceneCfg.screenMonster)
			{
				len = s._sceneCfg.screenMonster.length;		
				while(--len>-1)		
				{
					obj = s._sceneCfg.screenMonster[len];
					r = <Monster>s.createRoleByCfg(null, obj, obj.roleType, obj.sts, obj.dir, obj.absX, obj.absY);
					GameRole.roleDataSet(r, obj);					
				}				
			}			
		}
		/**进入场景*/
		public enterScene():void
		{
			super.enterScene();
			let s= this;
			s.sceneLogic.start();
			s.sceneLogic.netReady();						
		}
		/**获取默认的场景配置*/
		public getDefault():map2D.Default
		{
			let s= this;
			if(s._default == null)
				s._default = new GameDefault;
			return s._default;
		}
		/**创建特效或者飞行物体到场景中
		 * @param owner 特效拥有者
		 * @param effectID 特效ID		 
		 * @param absX 定位X
		 * @param absX 定位Y
		 * @param type 特效类型 EffectType特效类型
		 * @param gorupId 特效分组id		 
		 * @param dir 方向
		 * @param floatH 高度
		 * @param tarX 目标x，弹道使用
		 * @param tarY 目标y，弹道使用
		*/
		public createEffectToScene(owner:GameRole, effectID: string, absX: number = 0, absY: number = 0, type: EffectType = null, dir: number=0, floatH:number=0, layerType:number=NaN):ObjBase
		{
			let s = this;				
			type = type == null ? EffectType.SINGLE : type;
			if (type == EffectType.ATTACK) {//弹道特效				
				let driftObj: DriftObj;				
				driftObj = s.createDriftObj(owner, RoleType.DRIFT_OBJ, effectID, absX, absY + 1, StsType.ATTACK, dir);
				driftObj.floatH = floatH;				
				driftObj.effectType = type;
				return driftObj;
			}
			
			let effectObj: EffectObj;
			effectObj = s.createEffect(owner, RoleType.EFFECT, effectID, absX, absY, StsType.ATTACK, dir, layerType);
			effectObj.effectType = type;
			effectObj.floatH = floatH;			
			// effectObj.groupId = groupId;
			return effectObj;	
		}
		/**关卡胜负结果回调*/
		public gameEnd(win:boolean):void
		{
			let s= this;
			if(GameManager.getInstance().isGameOver)return;
			GameManager.getInstance().isGameOver = true;
			s.warnFlag = true;
			s.module.gameEnd(win);			
			s.module.dirBoard.touchEnd();
		}
		/**场景暂停(场景计时器和角色)*/
		public pause():boolean
		{			
			let s= this;			
			if(super.pause())
			{				
				s.pauseSceneRole(true);
				return true;
			}			
			return false;			
		}
		/**场景恢复(场景计时器和角色)*/
		public resume():boolean
		{		
			let s= this;	
			if(s.module.callUI && s.module.callUI.displayedInStage)
				return;
			if(super.resume())
			{	
				s.pauseSceneRole(false);
				return true;
			}			
			return false;			
		}
	}
}